Descriptors and values are passed by two distinct buffers.
Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
int xc_perfc_control(int xc_handle,
uint32_t opcode,
- xc_perfc_desc_t *desc)
+ xc_perfc_desc_t *desc,
+ xc_perfc_val_t *val,
+ int *nbr_desc,
+ int *nbr_val)
{
int rc;
DECLARE_DOM0_OP;
op.cmd = DOM0_PERFCCONTROL;
op.u.perfccontrol.op = opcode;
set_xen_guest_handle(op.u.perfccontrol.desc, desc);
+ set_xen_guest_handle(op.u.perfccontrol.val, val);
rc = do_dom0_op(xc_handle, &op);
- return (rc == 0) ? op.u.perfccontrol.nr_counters : rc;
+ if (nbr_desc)
+ *nbr_desc = op.u.perfccontrol.nr_counters;
+ if (nbr_val)
+ *nbr_val = op.u.perfccontrol.nr_vals;
+
+ return rc;
}
long long xc_msr_read(int xc_handle, int cpu_mask, int msr)
unsigned long mfn);
typedef dom0_perfc_desc_t xc_perfc_desc_t;
-/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
+typedef dom0_perfc_val_t xc_perfc_val_t;
+/* IMPORTANT: The caller is responsible for mlock()'ing the @desc and @val
+ arrays. */
int xc_perfc_control(int xc_handle,
uint32_t op,
- xc_perfc_desc_t *desc);
+ xc_perfc_desc_t *desc,
+ xc_perfc_val_t *val,
+ int *nbr_desc,
+ int *nbr_val);
/* read/write msr */
long long xc_msr_read(int xc_handle, int cpu_mask, int msr);
{
int i, j, xc_handle;
xc_perfc_desc_t *pcd;
- unsigned int num, sum, reset = 0, full = 0;
+ xc_perfc_val_t *pcv;
+ xc_perfc_val_t *val;
+ int num_desc, num_val;
+ unsigned int sum, reset = 0, full = 0;
if ( argc > 1 )
{
if ( reset )
{
if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET,
- NULL) < 0 )
+ NULL, NULL, NULL, NULL) != 0 )
{
fprintf(stderr, "Error reseting performance counters: %d (%s)\n",
errno, strerror(errno));
return 0;
}
+ if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+ NULL, NULL, &num_desc, &num_val) != 0 )
+ {
+ fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
- if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
- NULL)) < 0 )
- {
- fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
- errno, strerror(errno));
- return 1;
- }
-
- pcd = malloc(sizeof(*pcd) * num);
+ pcd = malloc(sizeof(*pcd) * num_desc);
+ pcv = malloc(sizeof(*pcv) * num_val);
- if ( mlock(pcd, sizeof(*pcd) * num) != 0 )
+ if ( pcd == NULL
+ || mlock(pcd, sizeof(*pcd) * num_desc) != 0
+ || pcv == NULL
+ || mlock(pcd, sizeof(*pcv) * num_val) != 0)
{
- fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n",
+ fprintf(stderr, "Could not alloc or mlock buffers: %d (%s)\n",
errno, strerror(errno));
exit(-1);
}
- if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 )
+ if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+ pcd, pcv, NULL, NULL) != 0 )
{
- fprintf(stderr, "Error getting perf counter description: %d (%s)\n",
+ fprintf(stderr, "Error getting perf counter: %d (%s)\n",
errno, strerror(errno));
return 1;
}
- munlock(pcd, sizeof(*pcd) * num);
+ munlock(pcd, sizeof(*pcd) * num_desc);
+ munlock(pcv, sizeof(*pcv) * num_val);
- for ( i = 0; i < num; i++ )
+ val = pcv;
+ for ( i = 0; i < num_desc; i++ )
{
printf ("%-35s ", pcd[i].name);
sum = 0;
for ( j = 0; j < pcd[i].nr_vals; j++ )
- sum += pcd[i].vals[j];
+ sum += val[j];
printf ("T=%10u ", (unsigned int)sum);
if ( full || (pcd[i].nr_vals <= 4) )
for ( j = 0; j < pcd[i].nr_vals; j++ )
- printf(" %10u", (unsigned int)pcd[i].vals[j]);
+ printf(" %10u", (unsigned int)val[j]);
printf("\n");
+ val += pcd[i].nr_vals;
}
return 0;
}
static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
+static dom0_perfc_val_t *perfc_vals;
+static int perfc_nbr_vals;
static int perfc_init = 0;
-static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc)
+static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc,
+ XEN_GUEST_HANDLE(dom0_perfc_val_t) val)
{
unsigned int i, j;
+ unsigned int v = 0;
atomic_t *counters = (atomic_t *)&perfcounters;
if ( guest_handle_is_null(desc) )
perfc_d[i].nr_vals = perfc_info[i].nr_elements;
break;
}
-
- if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) )
- perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals);
+ perfc_nbr_vals += perfc_d[i].nr_vals;
}
-
+ perfc_vals = xmalloc_array(dom0_perfc_val_t, perfc_nbr_vals);
perfc_init = 1;
}
+ if (perfc_vals == NULL)
+ return -ENOMEM;
/* We gather the counts together every time. */
for ( i = 0; i < NR_PERFCTRS; i++ )
{
case TYPE_SINGLE:
case TYPE_S_SINGLE:
- perfc_d[i].vals[0] = atomic_read(&counters[0]);
+ perfc_vals[v++] = atomic_read(&counters[0]);
counters += 1;
break;
case TYPE_CPU:
case TYPE_S_CPU:
for ( j = 0; j < perfc_d[i].nr_vals; j++ )
- perfc_d[i].vals[j] = atomic_read(&counters[j]);
+ perfc_vals[v++] = atomic_read(&counters[j]);
counters += NR_CPUS;
break;
case TYPE_ARRAY:
case TYPE_S_ARRAY:
for ( j = 0; j < perfc_d[i].nr_vals; j++ )
- perfc_d[i].vals[j] = atomic_read(&counters[j]);
+ perfc_vals[v++] = atomic_read(&counters[j]);
counters += perfc_info[i].nr_elements;
break;
}
}
+ BUG_ON(v != perfc_nbr_vals);
- return (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS) ?
- -EFAULT : 0);
+ if (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS))
+ return -EFAULT;
+ if (copy_to_guest(val, perfc_vals, perfc_nbr_vals))
+ return -EFAULT;
+ return 0;
}
/* Dom0 control of perf counters */
u32 op = pc->op;
int rc;
- pc->nr_counters = NR_PERFCTRS;
-
spin_lock(&lock);
switch ( op )
{
case DOM0_PERFCCONTROL_OP_RESET:
- perfc_copy_info(pc->desc);
+ perfc_copy_info(pc->desc, pc->val);
perfc_reset(0);
rc = 0;
break;
case DOM0_PERFCCONTROL_OP_QUERY:
- perfc_copy_info(pc->desc);
+ perfc_copy_info(pc->desc, pc->val);
rc = 0;
break;
spin_unlock(&lock);
+ pc->nr_counters = NR_PERFCTRS;
+ pc->nr_vals = perfc_nbr_vals;
+
return rc;
}
struct dom0_perfc_desc {
char name[80]; /* name of perf counter */
uint32_t nr_vals; /* number of values for this counter */
- uint32_t vals[64]; /* array of values */
};
typedef struct dom0_perfc_desc dom0_perfc_desc_t;
DEFINE_XEN_GUEST_HANDLE(dom0_perfc_desc_t);
+typedef uint32_t dom0_perfc_val_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_perfc_val_t);
struct dom0_perfccontrol {
/* IN variables. */
uint32_t op; /* DOM0_PERFCCONTROL_OP_??? */
/* OUT variables. */
- uint32_t nr_counters; /* number of counters */
+ uint32_t nr_counters; /* number of counters description */
+ uint32_t nr_vals; /* number of values */
XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc; /* counter information (or NULL) */
+ XEN_GUEST_HANDLE(dom0_perfc_val_t) val; /* counter values (or NULL) */
};
typedef struct dom0_perfccontrol dom0_perfccontrol_t;
DEFINE_XEN_GUEST_HANDLE(dom0_perfccontrol_t);